package com.acme.chat.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Class used to create new thread on each connected ChatClient.
 */
public class TCPServer implements Runnable {
    private static final String ERROR_SERVER_SOCKET_CREATION = "Can't create ServerSocket on the port: ";
    private static final String ERROR_CANT_ACCEPT_CONNECTON = "Can't accept connection on the socket: ";
    private static final String ERROR_CLOSING_SERVER = "Error closing the server: ";

    private volatile boolean keepGoing;

    private int port;
    private ServerSocket serverSocket;
    private Server server;

    /**
     * Constructor create TCPServer instance and set ServerSocket on the specified port.
     *
     * @param server
     * @param port
     */
    public TCPServer(Server server, int port) {
        this.server = server;
        this.port = port;
        init();
    }

    private void init() {
        try {
            this.serverSocket = new ServerSocket(port);
        } catch (IOException e) {
            System.out.println(ERROR_SERVER_SOCKET_CREATION + port);
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        keepGoing = true;
        while (keepGoing) {
            Socket socket = null;
            try {
                socket = serverSocket.accept();
            } catch (IOException e) {
                System.out.println(ERROR_CANT_ACCEPT_CONNECTON + socket);
                e.printStackTrace();
            }

            if (!keepGoing) {
                break;
            }

            // Create new thread on each connected client
            TCPClient client = new TCPClient(socket, server);
            client.start();
        }

        // Close socket then shutdown server
        try {
            serverSocket.close();
        } catch (IOException e1) {
            System.out.println(ERROR_CLOSING_SERVER);
            e1.printStackTrace();
        }
    }

    /**
     * Method stops accepting connections, stop thread and close serverSocket.
     */
    public void stop() {
        keepGoing = false;
        // TODO: this hack to wake up and stop server need change
        try {
            new Socket("localhost", port);
        } catch (IOException e) {
        }
    }


    public static void main(String[] args) {
        int portNumber = 6800;
        switch (args.length) {
        case 1:
            try {
                portNumber = Integer.parseInt(args[0]);
            } catch (Exception e) {
                System.out.println("Invalid port number.");
                System.out.println("Usage is: > java Server [portNumber]");
                return;
            }
        case 0:
            break;
        default:
            System.out.println("Usage is: > java Server [portNumber]");
            return;
        }

        TCPServer tcpServer = new TCPServer(new ServerImpl(), portNumber);
        (new Thread(tcpServer)).start();
    }

}
